//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
/*
;***
;llmul.asm - long multiply routine
;
;       Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
;
;Purpose:
;   Defines long multiply routine
;   Both signed and unsigned routines are the same, since multiply's
;   work out the same in 2's complement
;   creates the following routine:
;       __allmul
;
;******************************************************************************


;***
;llmul - long multiply routine
;
;Purpose:
;   Does a long multiply (same for signed/unsigned)
;   Parameters are not changed.
;
;Entry:
;   Parameters are passed on the stack:
;       1st pushed: multiplier (QWORD)
;       2nd pushed: multiplicand (QWORD)
;
;Exit:
;   EDX:EAX - product of multiplier and multiplicand
;   NOTE: parameters are removed from the stack
;
;Uses:
;   ECX
;
;Exceptions:
;
;*****************************************************************************/

//==========================================================================
// Copyright (c) 2000-2004,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
//
// The original program was copied from Microsoft Visual Studio 6.0
// Enterprise Edition.  This file is adapted for Zee operating system.
//==========================================================================

#include <elatypes.h>

__declspec(naked) void __cdecl _allmul(void)
{
    __asm {
#define ALO [esp + 4]   /* stack address of a loword */
#define AHI [esp + 8]   /* stack address of a hiword */
#define BLO [esp + 12]  /* stack address of b loword */
#define BHI [esp + 16]  /* stack address of b hiword */

;         ALO * BLO
;   ALO * BHI
; + BLO * AHI
; ---------------------
;

    mov eax,AHI
    mov ecx,BHI
    or  ecx,eax                     ;test for both hiwords zero.
    mov ecx,BLO
    jnz short hard                  ;both are zero, just mult ALO and BLO

    mov eax,ALO
    mul ecx

    ret 16                          ; callee restores the stack

hard:
    push    ebx

; must redefine A and B since esp has been altered
#define A2LO    [esp + 8]   /* stack address of a loword */
#define A2HI    [esp + 12]  /* stack address of a hiword */
#define B2LO    [esp + 16]  /* stack address of b loword */
#define B2HI    [esp + 20]  /* stack address of b hiword */

    mul ecx                         ;eax has AHI, ecx has BLO, so AHI * BLO
    mov ebx,eax                     ;save result

    mov eax,A2LO
    mul dword ptr B2HI              ;ALO * BHI
    add ebx,eax                     ;ebx = ((ALO * BHI) + (AHI * BLO))

    mov eax,A2LO                    ;ecx = BLO
    mul ecx                         ;so edx:eax = ALO*BLO
    add edx,ebx                     ;now edx has all the LO*HI stuff

    pop ebx

    ret 16                          ; callee restores the stack
    }
}
